import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shirne_dialog/shirne_dialog.dart';
import 'package:xml/xml.dart';
import 'package:file_picker/file_picker.dart';
import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';

import 'models/icon.dart';
import 'models/icon_export.dart';

class IconViewPage extends StatefulWidget {
  final IconFileItem item;

  const IconViewPage(this.item, {Key? key}) : super(key: key);
  @override
  State<StatefulWidget> createState() => _IconViewPageState();
}

class _IconViewPageState extends State<IconViewPage> {
  String fontFamily = '';
  bool isLoading = true;
  late Iterable<IconItem> codeMapAll;
  late Iterable<IconItem> codeMap;
  double itemWidth = 240;

  final FocusNode _searchFocus = FocusNode();

  @override
  void initState() {
    super.initState();

    loadFont();
  }

  loadFont() async {
    fontFamily = 'font_${widget.item.name}';
    FontLoader fontLoader = FontLoader(fontFamily);
    fontLoader.addFont(readFileAsByte(widget.item.file));
    await fontLoader.load();

    final file = File(widget.item.ttxFile);
    final document = XmlDocument.parse(await file.readAsString());

    final maps = document.findAllElements('cmap');
    final mapFormats = maps.first.getElement('cmap_format_4');
    final firstMap = mapFormats?.findElements('map');
    codeMap = codeMapAll = Iterable.generate(firstMap?.length ?? 0, (index) {
      final item = firstMap!.elementAt(index);
      return IconItem(
        item.getAttribute('name') ?? '',
        item.getAttribute('code') ?? '',
      );
    });
    setState(() {
      isLoading = false;
    });
  }

  doSearch(String key) {
    setState(() {
      codeMap = codeMapAll.where((element) => element.name.contains(key));
    });
  }

  Future<ByteData> readFileAsByte(String file) async {
    Uint8List data = File(file).readAsBytesSync();
    ByteData newData = ByteData(data.length);
    int offset = 0;
    for (var value in data) {
      newData.setUint8(offset, value);
      offset++;
    }
    return newData;
  }

  onExport() async {
    final size = MediaQuery.of(context).size;
    final type = await showMenu<IconExportType>(
        context: context,
        position:
            RelativeRect.fromLTRB(size.width - 110, 50, 10, size.height - 150),
        items: const [
          PopupMenuItem(
            child: Text('导出css'),
            value: IconExportType.css,
          ),
          PopupMenuItem(
            child: Text('导出dart'),
            value: IconExportType.dart,
          ),
        ]);
    if (type != null) {
      List<int> data = await exportIcons(widget.item.name, codeMap, type);
      String filename =
          '${widget.item.name}${type.toString().replaceFirst('IconExportType', '')}';
      if (kIsWeb) {
        //_saveFileWeb(data, filename);
      } else if (Platform.isAndroid || Platform.isIOS) {
        _saveFileMobile(data, filename);
      } else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
        _saveFileWindow(data, filename);
      }
    }
  }

  _saveFileMobile(List<int> content, String filename) async {
    String? result = await FilePicker.platform.getDirectoryPath();
    if (result != null && result.isNotEmpty) {
      TextEditingController filenameController =
          TextEditingController(text: filename);
      filenameController.addListener(() {
        filename = filenameController.text;
      });
      MyDialog.of(context)
          .confirm(
        TextField(
          controller: filenameController,
        ),
        buttonText: 'Save',
        title: '文件名',
      )
          .then((v) {
        if (v ?? false) {
          File('$result/$filename').writeAsBytes(content).then((File file) {
            MyDialog.of(context).toast('保存成功');
          });
        }
      });
    }
  }

  _saveFileWindow(List<int> content, String filename) async {
    final path = await FileSelectorPlatform.instance.getSaveLocation(
      acceptedTypeGroups: [
        const XTypeGroup(label: 'TrueType字体文件', extensions: ['.ttf'])
      ],
      options: SaveDialogOptions(suggestedName: filename),
    );
    if (path == null) {
      return;
    }

    File(path.path).writeAsBytes(content).then((File file) {
      MyDialog.of(context).toast('保存成功');
    });
  }

  @override
  Widget build(BuildContext context) {
    final _outlineInputBorder = OutlineInputBorder(
      borderRadius: BorderRadius.circular(20),
      borderSide: const BorderSide(color: Colors.white),
    );
    return GestureDetector(
      behavior: HitTestBehavior.translucent,
      onTap: () {
        _searchFocus.unfocus();
      },
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.item.name),
          toolbarHeight: 56,
          titleSpacing: 10,
          actions: [
            LimitedBox(
              maxWidth: 200,
              child: Padding(
                padding: const EdgeInsets.only(top: 8.0),
                child: TextField(
                  focusNode: _searchFocus,
                  onChanged: doSearch,
                  style: const TextStyle(color: Colors.white),
                  decoration: InputDecoration(
                    isCollapsed: true,
                    suffixIcon: const Icon(
                      Icons.search,
                      color: Colors.white,
                    ),
                    fillColor: const Color.fromARGB(50, 255, 255, 255),
                    filled: true,
                    hoverColor: const Color.fromARGB(50, 255, 255, 255),
                    focusColor: const Color.fromARGB(50, 255, 255, 255),
                    border: _outlineInputBorder,
                    focusedBorder: _outlineInputBorder,
                    enabledBorder: _outlineInputBorder,
                    hintText: 'Filter by name',
                    hintStyle: const TextStyle(color: Colors.white54),
                    contentPadding:
                        const EdgeInsets.symmetric(vertical: 13, horizontal: 8),
                  ),
                ),
              ),
            ),
            TextButton(
              onPressed: onExport,
              child: const Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Icon(
                    Icons.arrow_circle_down,
                    color: Colors.white,
                  ),
                  Text(
                    '导出',
                    style: TextStyle(color: Colors.white),
                  ),
                ],
              ),
            ),
            const SizedBox(width: 10),
          ],
        ),
        body: Container(
          padding: const EdgeInsets.all(20),
          child: isLoading
              ? const Center(child: CircularProgressIndicator())
              : viewIcon(),
        ),
      ),
    );
  }

  Widget viewIcon() {
    double width = MediaQuery.of(context).size.width;
    int count = width ~/ itemWidth;
    if (count < 1) {
      count = 1;
    }
    width = count * itemWidth;

    return Container(
      padding: const EdgeInsets.all(20),
      width: width,
      child: GridView.builder(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: count,
          childAspectRatio: 3,
        ),
        itemCount: codeMap.length,
        itemBuilder: (context, index) {
          var item = codeMap.elementAt(index);
          return IconItemWidget(
            item: item,
            fontFamily: fontFamily,
          );
        },
      ),
    );
  }
}

class IconItemWidget extends StatelessWidget {
  final IconItem item;
  final String fontFamily;

  const IconItemWidget({Key? key, required this.item, required this.fontFamily})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Stack(
        fit: StackFit.expand,
        children: [
          Padding(
            padding: const EdgeInsets.all(10),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                AspectRatio(
                  aspectRatio: 1,
                  child: Center(
                    child: Icon(
                      IconData(
                        int.parse(item.code),
                        fontFamily: fontFamily,
                      ),
                    ),
                  ),
                ),
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    CopyableWidget(
                      child: Text(item.code),
                      copyData: item.code,
                    ),
                    CopyableWidget(
                      child: Text(item.name, overflow: TextOverflow.ellipsis),
                      copyData: item.name,
                    ),
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class CopyableWidget extends StatelessWidget {
  final Widget child;
  final String copyData;
  final String success;

  const CopyableWidget(
      {Key? key,
      required this.copyData,
      required this.child,
      this.success = '复制成功'})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        Clipboard.setData(ClipboardData(text: copyData));
        MyDialog.of(context).toast(success, iconType: IconType.success);
      },
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          ConstrainedBox(
            constraints: const BoxConstraints(maxWidth: 120),
            child: child,
          ),
          const SizedBox(width: 5),
          const Icon(Icons.copy, size: 10),
        ],
      ),
    );
  }
}
